package com.dl.config.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.dl.properties.JWTProperties;
import com.dl.utils.EncodeUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author DL
 * @create 2021-06-10 16:19
 */

@Component
@EnableConfigurationProperties(JWTProperties.class)
@Log4j2
public class JwtTokenManager {

    @Resource
    private JWTProperties jwtProperties;

    /**
     * 签发令牌
     *  1.头部：密码，加密算法
     *  2.payload(负载)：签发时间，签发者，过期时间，唯一表示
     * @return
     */
    public String issueToken(String iss, long ttlMs, String sessionId, Map<String,Object> claims){
        if (ObjectUtils.isEmpty(claims)){
            claims = new HashMap<>();
        }

        //获取当前时间
        long nowMillisecond = System.currentTimeMillis();

        String encodedSecretKey = jwtProperties.getEncodedSecretKey();
        log.debug("encodedSecretKey:{}",encodedSecretKey);
        //获取加密签名，使用base64编码
        String secretKey = Base64.getEncoder().encodeToString(jwtProperties.getEncodedSecretKey().getBytes());
        log.debug("secretKey:{}",secretKey);
        //构建令牌
        JwtBuilder jwtBuilder = Jwts.builder()
                .setClaims(claims)//构建非隐私信息
                .setId(sessionId)//jti使用sessionId
                .setIssuedAt(new Date(nowMillisecond))//构建签发时间
                .setSubject(iss)//签发者
                .signWith(SignatureAlgorithm.HS256,secretKey);//指定算法和秘钥
        if (ttlMs > 0){
            long expMs = nowMillisecond + ttlMs;
            jwtBuilder.setExpiration(new Date(expMs));
        }
        return jwtBuilder.compact();
    }

    /**
     * 解析令牌
     * @param jwtToken
     * @return
     */
    public Claims deCodeToken(String jwtToken){
        String secretKey = Base64.getEncoder().encodeToString(jwtProperties.getEncodedSecretKey().getBytes());

        //使用秘钥解密字符串
        return Jwts.parser()
                .setSigningKey(secretKey)
                .parseClaimsJws(jwtToken)
                .getBody();
    }

    /**
     * 校验令牌：1.头部信息和荷载信息是否被篡改 2.令牌是否过期
     * @param jwtToken
     * @return
     */
    public boolean verifyToken(String jwtToken){

        //使用签名构建校验对象
        Algorithm algorithm = Algorithm.HMAC256(jwtProperties.getEncodedSecretKey());
        JWTVerifier jwtVerifier = JWT.require(algorithm).build();

        //校验不通过会抛出异常
        jwtVerifier.verify(jwtToken);
        return true;
    }
}
